import { ResponseDataModel } from './response-data-model';
import { InRequestConfig } from './in-request-config';
import { EnRequestContentType } from "./en-request-content-type";
import { EnRequestMethod } from './en-request-method';
import { getApplicationContainer } from '../../../get-application-container';

const CONTENT_TYPE_KEY = 'content-type';

export class HttpService {
    /**
     * 地址统一前缀
     */
    private _baseURL = 'https://www.xiaobokeji.cn/';

    /**
     * 正常返回数据的code
     */
    private _normalCode = 200;
    private _timeout = 100000;

    constructor(settings: ObjectMap) {
        if (settings['baseUrl']) {
            this._baseURL = settings['baseUrl'];
        }
        if (settings['timeout']) {
            this._timeout = settings['timeout'];
        }
        if (settings['normalCode']) {
            this._normalCode = settings['normalCode'];
        }
    }

    public get<T>(url: string, data?: any): Promise<T> {
        return this.request<T>({
            url,
            data,
            method: EnRequestMethod.get
        }, EnRequestContentType.get);
    }
    

    /**
     * 以json的数据格式进行请求
     * @param url 请求地址
     * @param data 请求的数据
     * @param method 方式
     */
    public json<T>(url: string, data?: any): Promise<T> {
        return this.request<T>({
            url,
            data,
            method: EnRequestMethod.post,
        }, EnRequestContentType.json);
    }

    /**
     * 以form表单提交数据
     * @param url 请求地址
     * @param data 请求携带的数据
     */
    public async post<T>(url: string, data?: any): Promise<T> {
        return await this.request<T>({
            url,
            data,
            method: EnRequestMethod.post
        }, EnRequestContentType.form);
    }

    /**
     * 文件上传
     * @param url 请求地址
     * @param data 请求携带的表单数据
     */
    public async upload<T>(url: string, data: any): Promise<T> {
        return await this.request<T>({
            url,
            data,
            method: EnRequestMethod.post
        }, EnRequestContentType.file)
    }

    /**
     * cookie
     */
    public getCookie() {
        const token = getApplicationContainer​​().authService.token;
        if (token) {
            return `ACCESS_TOKEN=${token}`;
        } else {
            return '';
        }
    }

    public request<T>(config: InRequestConfig, contentType: EnRequestContentType): Promise<T> {
        let header = { ...config.header } as any;
        let url = `${this._baseURL}${config.url}`;
        let data = config.data;

        // 配置好header
        if (!header[CONTENT_TYPE_KEY]) {
            header[CONTENT_TYPE_KEY] = contentType;
        }
        header['Cookie'] = this.getCookie();
        // 配置好提交的数据
        // get请求参数直接拼接
        if (contentType == EnRequestContentType.get) {
            Object.keys(config.data || {}).forEach(key => {
                url += url.indexOf("?") === -1 ? "?" : "&";
                url += key + "=" + encodeURIComponent(config.data[key]);
            });
        }
        return new Promise((resolve, reject) => {
            wx.request({
                url,
                header,
                data: data || {},
                timeout: config.timeout || this._timeout,
                method: config.method,
                dataType: config.dataType || 'json',
                success: (res) => {
                    
                    let r = res.data as ResponseDataModel<T>;
                    // 符合返回数据的正确格式
                    if (typeof r == 'object' && r.code !== undefined) {
                        if (r.code == this._normalCode) {
                            resolve(r.data);
                        } else {
                            reject({message: r.message, code: r.code});
                        }
                    } else {
                        // 不符合直接返回数据
                        resolve(r as any as T);
                    }
                },
                fail: (error) => {
                    console.log(error.errMsg);
                    error.errMsg = "服务升级，请稍后再试！";
                    reject(error.errMsg);
                }
            } as WechatMiniprogram.RequestOption);
        });
    }
}